import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
//AnimatedList提供了一种简单的方式使列表数据发生变化时加入过渡动画
/*
列表数据的插入和删除有进出场动画需要调用AnimatedListState指定的方法，只删除原数据并调用setState方法是没有动画效果的，对应方法如下：

AnimatedListState.insertItem
AnimatedListState.removeItem

AnimatedListState是AnimatedList的状态类，获取AnimatedListState有两个方法：

通过AnimatedList.of(context)方法，代码如下：
AnimatedList.of(context).insertItem(index);
AnimatedList.of(context).removeItem(index, (context,animation)=>{});
1
2
2） 通过设置key，用法如下：

final GlobalKey<AnimatedListState> _listKey = GlobalKey<AnimatedListState>();
 */
class AnimatedListSample extends StatefulWidget{
  @override
  State<StatefulWidget> createState() {
    return _AnimatedListSampleState();
  }
}

class ListMode<E>{
  ListMode({required this.listKey, required this.removedItemBuilder, Iterable<E>? initialItems}):
      assert(listKey != null), assert(removedItemBuilder != null), _items = new List<E>.from(initialItems??<E>[]);
      final GlobalKey<AnimatedListState> listKey;
      final dynamic removedItemBuilder;
      final List<E> _items;

      AnimatedListState get _animatedList => listKey.currentState!;

      void insert(int index, E item){
        _items.insert(index, item);
        _animatedList.insertItem(index);
      }

      E removeAt(int index){
        final E removedItem = _items.removeAt(index);
        if(removedItem != null){
          _animatedList.removeItem(index, (context, animation) => removedItemBuilder(removedItem, context, animation));
        }
        return removedItem;
      }

      int get lenght => _items.length;
      E operator [](int index) => _items[index];
      int indexOf(E item) => _items.indexOf(item);
}

class CardItem extends StatelessWidget{
  const CardItem({Key? key,
    required this.animation,
    this.onTap,
    required this.item,
    this.selected: false
  }) : assert(animation != null),
       assert(item != null && item >= 0),
       assert(selected != null),
       super(key: key);
  final Animation<double> animation;
  final VoidCallback? onTap;
  final bool selected;
  final int item;

  @override
  Widget build(BuildContext context) {
    TextStyle textStyle = Theme.of(context).textTheme.display1!;
    if(selected)
      {
        textStyle = textStyle.copyWith(color: Colors.lightGreenAccent[400]);
      }
    return Padding(padding: EdgeInsets.all(2.0),
    child: SizeTransition(sizeFactor: animation,
    axis: Axis.vertical,
    child: GestureDetector(
      behavior: HitTestBehavior.opaque,
      onTap: onTap,
      child: SizedBox(
        height: 128.0,
        child: Card(
          color: Colors.primaries[item % Colors.primaries.length],
          child: Center(child: Text('Item $item', style: textStyle,),),
        ),
      ),
    ),),);
  }
}

class _AnimatedListSampleState extends State<AnimatedListSample>
{
  final GlobalKey<AnimatedListState> _listKey = GlobalKey<AnimatedListState>();
  late ListMode<int> _list;
  int? _selectedItem;
  late int _nextItem;

  @override
  void initState() {
    super.initState();
    _list = ListMode<int>(listKey: _listKey, initialItems:<int>[0,1,2],removedItemBuilder: _buildRemovedItem);
    _nextItem = 3;
  }

  Widget _buildItem(BuildContext context, int index, Animation<double> animation){
    return CardItem(animation: animation, item: _list[index],selected: _selectedItem == _list[index],
    onTap: (){
      setState(() {
        _selectedItem = _selectedItem == _list[index] ? null : _list[index];
      });
    },);
  }
  
  Widget _buildRemovedItem(int item, BuildContext context, Animation<double> animation){
    return CardItem(animation: animation, item: item, selected: false,);
  }

  void _insert(){
    final int index =  _selectedItem == null? _list.lenght : _list.indexOf(_selectedItem!);
    _list.insert(index, _nextItem++);
  }

  void _remove(){
    if(_selectedItem != null){
      _list.removeAt(_list.indexOf(_selectedItem!));
      setState(() {
        _selectedItem = null;
      });
    }
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('AnimatedList'),
      actions: [
        IconButton(onPressed: _insert, icon: const Icon(Icons.add_circle),tooltip: 'insert a new item',),
        IconButton(onPressed: _remove, icon: const Icon(Icons.remove_circle), tooltip: 'remove the selected time',),
      ],),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: AnimatedList(
          key: _listKey,
          initialItemCount: _list.lenght,
          itemBuilder: _buildItem,
        ),
      ),
    );
  }
}